package modules.java8.stream2;

import modules.dao.UserRepository;
import modules.entities.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.*;
import java.util.stream.Collectors;

/**
 * Stream流式计算 2
 *      排序
 *      查找与匹配
 *      规约与收集
 *
 * @create 2021-03-16
 */
@SpringBootTest
public class Stream2 {

    @Autowired
    UserRepository userRepository;

    // 排序
    @Test
    void test3() {
        List<User> list = userRepository.findAll();
        list.forEach(System.out::println);
        // sorted()  自然排序  sorted(Comparator)  定制排序
        System.out.println("--------- 自然排序 ----------");

        // 按ID排序，倒序
//        list.stream().sorted((e1,e2)->{
//           return -Integer.compare(e1.getId(),e2.getId());
//        }).forEach(System.out::println);

        // 按名字排序，倒序，如果名字一样，按照ID排序，倒序
//        list.stream().sorted((e1, e2) -> {
//            if (e1.getGender() == e2.getGender()) {
//                return e1.getUsername().compareTo(e2.getUsername());
//            } else {
//                return Integer.compare(e1.getGender(), e2.getGender());
//            }
//        }).forEach(System.out::println);

        // Comparator排序 按ID排序，倒序 加上 reversed()
//        list.stream().sorted(Comparator.comparing(User::getId).reversed()).forEach(System.out::println);

        // Comparator排序 再根据姓名比较排序  使用 thenComparing
//        list.stream().sorted(Comparator.comparingInt(User::getGender).reversed()
//                        .thenComparing(User::getUsername).reversed()
//                       ).forEach(System.out::println);

        // 当集合中存在null元素时，null元素排在集合的最前面  nullsFirst , 最后面  nullsLast
//        list.add(null);
//        list.stream().sorted(Comparator.nullsFirst(Comparator.comparing(User::getId))).forEach(System.out::println);

        //  //对 Double类型排序
//        list.stream().sorted((x1,x2)->{
//            return Double.compare(x1.getId(),x2.getId());
//         });

    }

    // 查找与匹配
    @Test
    void test4() {

        List<User> list = userRepository.findAll();
        list.forEach(System.out::println);

        // 检查是否匹配所有元素  allMatch
//        System.out.println(" 检查是否匹配所有元素 ---------------");
//        boolean allMatch = list.stream().allMatch(e -> {return e.getGender() == 2; });
//        System.out.println(allMatch);  // false

        // 检查是否匹至少匹配一个元素
//        System.out.println("---------------");
//        boolean anyMatch = list.stream().anyMatch(e -> { return e.getUsername().equals("lisi");});
//        System.out.println(anyMatch);  // true

        // 检查是否没有匹配所有元素  noneMatch
//        System.out.println("---------------");
//        boolean noneMatch = list.stream().noneMatch( e ->{return e.getUsername().equals("lisi");});
//        System.out.println(noneMatch);  // false

        // 返回第一个元素  findFirst   避免空指针异常
//        System.out.println(" 返回第一个元素 ---------------");
//        Optional<User> first = list.stream().findFirst();
//        User user = first.get();
//        System.out.println(user);

        // 返回流中任意元素  findAny   parallelStream是并行流（多个线程同时获取）
        // orElse 默认值，如果没有符合条件 返回默认值
//        System.out.println("---------------");
//        User user = list.parallelStream().findAny().orElse(null);
//        System.out.println(user);

        // 返回流中元素个数  count
//        System.out.println(" 返回流中元素个数 ---------------");
//        long count = list.stream().count();
//        System.out.println(count);

        // 返回流中最大值  count
//        System.out.println(" 返回流中最大值 ---------------");
//        Optional<User> max = list.stream().max((e1, e2) -> {
//            return Integer.compare(e1.getId(), e2.getId());
//        });
//        System.out.println(max.get());

        // 返回流中最小值  count
//        System.out.println(" 返回流中最小值 ---------------");
//        Optional<Integer> min = list.stream()
//                .map(User::getId)
//                .min((e1, e2) -> {
//                    return Integer.compare(e1, e2);
//                });
//        // 简写 ： .min(Integer::compare);
//        System.out.println(min.get());

    }


    // 规约/收集
    @Test
    void test5() {

        List<User> list = userRepository.findAll();
        list.forEach(System.out::println);

        // 规约 - 将流中元素结合起来得到一个值
//        System.out.println("求和：————————————————");
//        Optional<Integer> reduce = list.stream().map(User::getId).reduce(Integer::sum);
//        Integer integer = reduce.get();
//        System.out.println(integer);

        // 收集 - 将流转换为其他形式，接受Collector接口实现，汇总方式
//        List<String> collect1 = list.stream().map(User::getUsername).collect(Collectors.toList());
//        System.out.println(collect1);
//        System.out.println("-------- 转Set ----------");
//        Set<String> collect2 = list.stream().map(User::getUsername).collect(Collectors.toSet());
//        System.out.println(collect2);
//        System.out.println("-------- 转HashSet ----------");
//        HashSet<String> collect3 = list.stream().map(User::getUsername).collect(Collectors.toCollection(HashSet::new));
//        System.out.println(collect3);

        // 总数
        Long count = list.stream().collect(Collectors.counting());
        System.out.println("总数" + count);

        // 平均值
        Double avg = list.stream().collect(Collectors.averagingInt(User::getId));
        System.out.println("平均值" + avg);

        // 总和
        Integer sum = list.stream().collect(Collectors.summingInt(User::getId));
        System.out.println("总和" + sum);

        // 最大值
        Optional<User> max = list.stream().collect(Collectors.maxBy((e1, e2) -> {
            return Integer.compare(e1.getId(), e2.getId());
        }));
        System.out.println("最大值对象" + max.get());

        // 最小值
        Optional<Integer> min = list.stream()
                .map(User::getId).collect(Collectors.minBy(Integer::compare));
        System.out.println("最小值对象" + min.get());

    }

}
